home *** CD-ROM | disk | FTP | other *** search
- /*
- * Modifications Copyright 1993, 1994, 1995, 1996, 1999, 2000 by Paul Mattes.
- * Original X11 Port Copyright 1990 by Jeff Sparkes.
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * Copyright 1989 by Georgia Tech Research Corporation, Atlanta, GA 30332.
- * All Rights Reserved. GTRC hereby grants public use of this software.
- * Derivative works based on this software must incorporate this copyright
- * notice.
- */
-
- /*
- * ctlr.c
- * This module handles interpretation of the 3270 data stream and
- * maintenance of the 3270 device state. It was split out from
- * screen.c, which handles X operations.
- *
- */
-
- #include "globals.h"
- #include <errno.h>
- #include "3270ds.h"
- #include "appres.h"
- #include "ctlr.h"
- #include "screen.h"
- #include "cg.h"
- #include "resources.h"
-
- #include "ctlrc.h"
- #include "ftc.h"
- #include "ft_cutc.h"
- #include "hostc.h"
- #include "kybdc.h"
- #include "macrosc.h"
- #include "popupsc.h"
- #include "screenc.h"
- #include "scrollc.h"
- #include "selectc.h"
- #include "sfc.h"
- #include "statusc.h"
- #include "tablesc.h"
- #include "telnetc.h"
- #include "trace_dsc.h"
- #include "utilc.h"
-
- /* Externals: kybd.c */
- extern unsigned char aid;
-
- /* Globals */
- int ROWS, COLS;
- int maxROWS, maxCOLS;
- int ov_rows, ov_cols;
- int model_num;
- int cursor_addr, buffer_addr;
- Boolean screen_alt = True; /* alternate screen? */
- Boolean is_altbuffer = False;
- unsigned char *screen_buf; /* 3270 display buffer */
- struct ea *ea_buf; /* 3270 extended attribute buffer */
- Boolean formatted = False; /* set in screen_disp */
- Boolean screen_changed = False;
- int first_changed = -1;
- int last_changed = -1;
- unsigned char reply_mode = SF_SRM_FIELD;
- int crm_nattr = 0;
- unsigned char crm_attr[16];
-
- /* Statics */
- static unsigned char *ascreen_buf; /* alternate 3270 display buffer */
- static struct ea *aea_buf; /* alternate 3270 extended attribute buffer */
- static unsigned char *zero_buf; /* empty buffer, for area clears */
- static void set_formatted(void);
- static void ctlr_blanks(void);
- static unsigned char fake_fa;
- static struct ea fake_ea;
- static Boolean trace_primed = False;
- static unsigned char default_fg;
- static unsigned char default_gr;
- static unsigned char default_cs;
- static void ctlr_half_connect(Boolean ignored);
- static void ctlr_connect(Boolean ignored);
- static int sscp_start;
- static void ticking_stop(void);
-
- /*
- * code_table is used to translate buffer addresses and attributes to the 3270
- * datastream representation
- */
- static unsigned char code_table[64] = {
- 0x40, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
- 0xC8, 0xC9, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
- 0x50, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
- 0xD8, 0xD9, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
- 0x60, 0x61, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
- 0xE8, 0xE9, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
- 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
- 0xF8, 0xF9, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
- };
-
- #define IsBlank(c) ((c == CG_null) || (c == CG_space))
-
- #define ALL_CHANGED { \
- screen_changed = True; \
- if (IN_ANSI) { first_changed = 0; last_changed = ROWS*COLS; } }
- #define REGION_CHANGED(f, l) { \
- screen_changed = True; \
- if (IN_ANSI) { \
- if (first_changed == -1 || f < first_changed) first_changed = f; \
- if (last_changed == -1 || l > last_changed) last_changed = l; } }
- #define ONE_CHANGED(n) REGION_CHANGED(n, n+1)
-
- #define DECODE_BADDR(c1, c2) \
- ((((c1) & 0xC0) == 0x00) ? \
- (((c1) & 0x3F) << 8) | (c2) : \
- (((c1) & 0x3F) << 6) | ((c2) & 0x3F))
-
- #define ENCODE_BADDR(ptr, addr) { \
- if ((addr) > 0xfff) { \
- *(ptr)++ = ((addr) >> 8) & 0x3F; \
- *(ptr)++ = (addr) & 0xFF; \
- } else { \
- *(ptr)++ = code_table[((addr) >> 6) & 0x3F]; \
- *(ptr)++ = code_table[(addr) & 0x3F]; \
- } \
- }
-
- /*
- * Initialize the emulated 3270 hardware.
- */
- void
- ctlr_init(unsigned cmask unused)
- {
- /* Register callback routines. */
- register_schange(ST_HALF_CONNECT, ctlr_half_connect);
- register_schange(ST_CONNECT, ctlr_connect);
- register_schange(ST_3270_MODE, ctlr_connect);
- }
- /*
- * Reinitialize the emulated 3270 hardware.
- */
- void
- ctlr_reinit(unsigned cmask)
- {
- if (cmask & MODEL_CHANGE) {
- /* Allocate buffers */
- if (screen_buf)
- Free((char *)screen_buf);
- screen_buf = (unsigned char *)Calloc(sizeof(unsigned char),
- maxROWS * maxCOLS);
- if (ea_buf)
- Free((char *)ea_buf);
- ea_buf = (struct ea *)Calloc(sizeof(struct ea),
- maxROWS * maxCOLS);
- if (ascreen_buf)
- Free((char *)ascreen_buf);
- ascreen_buf = (unsigned char *)Calloc(sizeof(unsigned char),
- maxROWS * maxCOLS);
- if (aea_buf)
- Free((char *)aea_buf);
- aea_buf = (struct ea *)Calloc(sizeof(struct ea),
- maxROWS * maxCOLS);
- if (zero_buf)
- Free((char *)zero_buf);
- zero_buf = (unsigned char *)Calloc(sizeof(struct ea),
- maxROWS * maxCOLS);
- cursor_addr = 0;
- buffer_addr = 0;
- }
- }
-
- /*
- * Deal with the relationships between model numbers and rows/cols.
- */
- void
- set_rows_cols(int mn, int ovc, int ovr)
- {
- int defmod;
-
- switch (mn) {
- case 2:
- maxCOLS = COLS = 80;
- maxROWS = ROWS = 24;
- model_num = 2;
- break;
- case 3:
- maxCOLS = COLS = 80;
- maxROWS = ROWS = 32;
- model_num = 3;
- break;
- case 4:
- #if defined(RESTRICT_3279) /*[*/
- if (appres.m3279) {
- Warning("No 3279 Model 4, defaulting to Model 3");
- set_rows_cols("3", ovc, ovr);
- return;
- }
- #endif /*]*/
- maxCOLS = COLS = 80;
- maxROWS = ROWS = 43;
- model_num = 4;
- break;
- case 5:
- #if defined(RESTRICT_3279) /*[*/
- if (appres.m3279) {
- Warning("No 3279 Model 5, defaulting to Model 3");
- set_rows_cols(3, ovc, ovr);
- return;
- }
- #endif /*]*/
- maxCOLS = COLS = 132;
- maxROWS = ROWS = 27;
- model_num = 5;
- break;
- default:
- #if defined(RESTRICT_3279) /*[*/
- defmod = appres.m3279 ? 3 : 4;
- #else /*][*/
- defmod = 4;
- #endif
- {
- char mnb[2];
-
- mnb[0] = defmod + '0';
- mnb[1] = '\0';
- xs_warning("Unknown model, defaulting to %s", mnb);
- }
- set_rows_cols(defmod, ovc, ovr);
- return;
- }
-
- /* Apply oversize. */
- ov_cols = 0;
- ov_rows = 0;
- if (ovc != 0 || ovr != 0) {
- if (ovc <= 0 || ovr <= 0)
- popup_an_error("Invalid %s %dx%d:\nNegative or zero",
- ResOversize, ovc, ovr);
- else if (ovc * ovr >= 0x4000)
- popup_an_error("Invalid %s %dx%d:\nToo big",
- ResOversize, ovc, ovr);
- else if (ovc > 0 && ovc < maxCOLS)
- popup_an_error("Invalid %s cols (%d):\nLess than model %d cols (%d)",
- ResOversize, ovc, model_num, maxCOLS);
- else if (ovr > 0 && ovr < maxROWS)
- popup_an_error("Invalid %s rows (%d):\nLess than model %d rows (%d)",
- ResOversize, ovr, model_num, maxROWS);
- else {
- ov_cols = maxCOLS = COLS = ovc;
- ov_rows = maxROWS = ROWS = ovr;
- }
- }
-
- /* Update the model name. */
- (void) sprintf(model_name, "327%c-%d%s",
- appres.m3279 ? '9' : '8',
- model_num,
- appres.extended ? "-E" : "");
- }
-
-
- /*
- * Set the formatted screen flag. A formatted screen is a screen that
- * has at least one field somewhere on it.
- */
- static void
- set_formatted(void)
- {
- register int baddr;
-
- formatted = False;
- baddr = 0;
- do {
- if (IS_FA(screen_buf[baddr])) {
- formatted = True;
- break;
- }
- INC_BA(baddr);
- } while (baddr != 0);
- }
-
- /*
- * Called when a host is half connected.
- */
- static void
- ctlr_half_connect(Boolean ignored unused)
- {
- ticking_start(True);
- }
-
-
- /*
- * Called when a host connects, disconnects, or changes ANSI/3270 modes.
- */
- static void
- ctlr_connect(Boolean ignored unused)
- {
- ticking_stop();
- status_untiming();
-
- if (ever_3270)
- fake_fa = 0xE0;
- else
- fake_fa = 0xC4;
- if (!IN_3270 || (IN_SSCP && (kybdlock & KL_OIA_TWAIT))) {
- kybdlock_clr(KL_OIA_TWAIT, "ctlr_connect");
- status_reset();
- }
-
- default_fg = 0x00;
- default_gr = 0x00;
- default_cs = 0x00;
- reply_mode = SF_SRM_FIELD;
- crm_nattr = 0;
- }
-
-
- /*
- * Find the field attribute for the given buffer address. Return its address
- * rather than its value.
- */
- unsigned char *
- get_field_attribute(register int baddr)
- {
- int sbaddr;
-
- if (!formatted)
- return &fake_fa;
-
- sbaddr = baddr;
- do {
- if (IS_FA(screen_buf[baddr]))
- return &(screen_buf[baddr]);
- DEC_BA(baddr);
- } while (baddr != sbaddr);
- return &fake_fa;
- }
-
- /*
- * Find the field attribute for the given buffer address, bounded by another
- * buffer address. Return the attribute in a parameter.
- *
- * Returns True if an attribute is found, False if boundary hit.
- */
- Boolean
- get_bounded_field_attribute(register int baddr, register int bound, unsigned char *fa_out)
- {
- int sbaddr;
-
- if (!formatted) {
- *fa_out = fake_fa;
- return True;
- }
-
- sbaddr = baddr;
- do {
- if (IS_FA(screen_buf[baddr])) {
- *fa_out = screen_buf[baddr];
- return True;
- }
- DEC_BA(baddr);
- } while (baddr != sbaddr && baddr != bound);
-
- /* Screen is unformatted (and 'formatted' is inaccurate). */
- if (baddr == sbaddr) {
- *fa_out = fake_fa;
- return True;
- }
-
- /* Wrapped to boundary. */
- return False;
- }
-
- /*
- * Given the address of a field attribute, return the address of the
- * extended attribute structure.
- */
- struct ea *
- fa2ea(unsigned char *fa)
- {
- if (fa == &fake_fa)
- return &fake_ea;
- else
- return &ea_buf[fa - screen_buf];
- }
-
- /*
- * Find the next unprotected field. Returns the address following the
- * unprotected attribute byte, or 0 if no nonzero-width unprotected field
- * can be found.
- */
- int
- next_unprotected(int baddr0)
- {
- register int baddr, nbaddr;
-
- nbaddr = baddr0;
- do {
- baddr = nbaddr;
- INC_BA(nbaddr);
- if (IS_FA(screen_buf[baddr]) &&
- !FA_IS_PROTECTED(screen_buf[baddr]) &&
- !IS_FA(screen_buf[nbaddr]))
- return nbaddr;
- } while (nbaddr != baddr0);
- return 0;
- }
-
- /*
- * Perform an erase command, which may include changing the (virtual) screen
- * size.
- */
- void
- ctlr_erase(Boolean alt)
- {
- kybd_inhibit(False);
-
- ctlr_clear(True);
-
- /* Let a script go. */
- sms_host_output();
-
- if (alt == screen_alt)
- return;
-
- screen_disp();
-
- if (alt) {
- /* Going from 24x80 to maximum. */
- screen_disp();
- ROWS = maxROWS;
- COLS = maxCOLS;
- } else {
- /* Going from maximum to 24x80. */
- if (maxROWS > 24 || maxCOLS > 80) {
- if (*debugging_font) {
- ctlr_blanks();
- screen_disp();
- }
- ROWS = 24;
- COLS = 80;
- }
- }
-
- screen_alt = alt;
- }
-
-
- /*
- * Interpret an incoming 3270 command.
- */
- enum pds
- process_ds(unsigned char *buf, int buflen)
- {
- if (!buflen)
- return PDS_OKAY_NO_OUTPUT;
-
- scroll_to_bottom();
-
- trace_ds("< ");
-
- switch (buf[0]) { /* 3270 command */
- case CMD_EAU: /* erase all unprotected */
- case SNA_CMD_EAU:
- trace_ds("EraseAllUnprotected\n");
- ctlr_erase_all_unprotected();
- return PDS_OKAY_NO_OUTPUT;
- break;
- case CMD_EWA: /* erase/write alternate */
- case SNA_CMD_EWA:
- trace_ds("EraseWriteAlternate");
- ctlr_erase(True);
- ctlr_write(buf, buflen, True);
- return PDS_OKAY_NO_OUTPUT;
- break;
- case CMD_EW: /* erase/write */
- case SNA_CMD_EW:
- trace_ds("EraseWrite");
- ctlr_erase(False);
- ctlr_write(buf, buflen, True);
- return PDS_OKAY_NO_OUTPUT;
- break;
- case CMD_W: /* write */
- case SNA_CMD_W:
- trace_ds("Write");
- ctlr_write(buf, buflen, False);
- return PDS_OKAY_NO_OUTPUT;
- break;
- case CMD_RB: /* read buffer */
- case SNA_CMD_RB:
- trace_ds("ReadBuffer\n");
- ctlr_read_buffer(aid);
- return PDS_OKAY_OUTPUT;
- break;
- case CMD_RM: /* read modifed */
- case SNA_CMD_RM:
- trace_ds("ReadModified\n");
- ctlr_read_modified(aid, False);
- return PDS_OKAY_OUTPUT;
- break;
- case CMD_RMA: /* read modifed all */
- case SNA_CMD_RMA:
- trace_ds("ReadModifiedAll\n");
- ctlr_read_modified(aid, True);
- return PDS_OKAY_OUTPUT;
- break;
- case CMD_WSF: /* write structured field */
- case SNA_CMD_WSF:
- trace_ds("WriteStructuredField");
- return write_structured_field(buf, buflen);
- break;
- case CMD_NOP: /* no-op */
- trace_ds("NoOp\n");
- return PDS_OKAY_NO_OUTPUT;
- break;
- default:
- /* unknown 3270 command */
- popup_an_error("Unknown 3270 Data Stream command: 0x%X\n",
- buf[0]);
- return PDS_BAD_CMD;
- }
- }
-
- /*
- * Functions to insert SA attributes into the inbound data stream.
- */
- static void
- insert_sa1(unsigned char attr, unsigned char value, unsigned char *currentp, Boolean *anyp)
- {
- if (value == *currentp)
- return;
- *currentp = value;
- space3270out(3);
- *obptr++ = ORDER_SA;
- *obptr++ = attr;
- *obptr++ = value;
- if (*anyp)
- trace_ds("'");
- trace_ds(" SetAttribute(%s)", see_efa(attr, value));
- *anyp = False;
- }
-
- static void
- insert_sa(int baddr, unsigned char *current_fgp, unsigned char *current_grp, unsigned char *current_csp, Boolean *anyp)
- {
- if (reply_mode != SF_SRM_CHAR)
- return;
-
- if (memchr((char *)crm_attr, XA_FOREGROUND, crm_nattr))
- insert_sa1(XA_FOREGROUND, ea_buf[baddr].fg, current_fgp, anyp);
- if (memchr((char *)crm_attr, XA_HIGHLIGHTING, crm_nattr)) {
- unsigned char gr;
-
- gr = ea_buf[baddr].gr;
- if (gr)
- gr |= 0xf0;
- insert_sa1(XA_HIGHLIGHTING, gr, current_grp, anyp);
- }
- if (memchr((char *)crm_attr, XA_CHARSET, crm_nattr)) {
- unsigned char cs;
-
- cs = ea_buf[baddr].cs & CS_MASK;
- if (cs)
- cs |= 0xf0;
- insert_sa1(XA_CHARSET, cs, current_csp, anyp);
- }
- }
-
-
- /*
- * Process a 3270 Read-Modified command and transmit the data back to the
- * host.
- */
- void
- ctlr_read_modified(unsigned char aid_byte, Boolean all)
- {
- register int baddr, sbaddr;
- Boolean send_data = True;
- Boolean short_read = False;
- unsigned char current_fg = 0x00;
- unsigned char current_gr = 0x00;
- unsigned char current_cs = 0x00;
-
- if (IN_SSCP && aid_byte != AID_ENTER)
- return;
-
- trace_ds("> ");
- obptr = obuf;
-
- switch (aid_byte) {
-
- case AID_SYSREQ: /* test request */
- space3270out(4);
- *obptr++ = 0x01; /* soh */
- *obptr++ = 0x5b; /* % */
- *obptr++ = 0x61; /* / */
- *obptr++ = 0x02; /* stx */
- trace_ds("SYSREQ");
- break;
-
- case AID_PA1: /* short-read AIDs */
- case AID_PA2:
- case AID_PA3:
- case AID_CLEAR:
- if (!all)
- short_read = True;
- /* fall through... */
-
- case AID_SELECT: /* No data on READ MODIFIED */
- if (!all)
- send_data = False;
- /* fall through... */
-
- default: /* ordinary AID */
- if (!IN_SSCP) {
- space3270out(3);
- *obptr++ = aid_byte;
- trace_ds(see_aid(aid_byte));
- if (short_read)
- goto rm_done;
- ENCODE_BADDR(obptr, cursor_addr);
- trace_ds(rcba(cursor_addr));
- } else {
- space3270out(1); /* just in case */
- }
- break;
- }
-
- baddr = 0;
- if (formatted) {
- /* find first field attribute */
- do {
- if (IS_FA(screen_buf[baddr]))
- break;
- INC_BA(baddr);
- } while (baddr != 0);
- sbaddr = baddr;
- do {
- if (FA_IS_MODIFIED(screen_buf[baddr])) {
- Boolean any = False;
-
- INC_BA(baddr);
- space3270out(3);
- *obptr++ = ORDER_SBA;
- ENCODE_BADDR(obptr, baddr);
- trace_ds(" SetBufferAddress%s", rcba(baddr));
- while (!IS_FA(screen_buf[baddr])) {
- if (send_data &&
- screen_buf[baddr]) {
- insert_sa(baddr,
- ¤t_fg,
- ¤t_gr,
- ¤t_cs,
- &any);
- if (ea_buf[baddr].cs & CS_GE) {
- space3270out(1);
- *obptr++ = ORDER_GE;
- if (any)
- trace_ds("'");
- trace_ds(" GraphicEscape");
- any = False;
- }
- space3270out(1);
- *obptr++ = cg2ebc[screen_buf[baddr]];
- if (!any)
- trace_ds(" '");
- trace_ds("%s", see_ebc(cg2ebc[screen_buf[baddr]]));
- any = True;
- }
- INC_BA(baddr);
- }
- if (any)
- trace_ds("'");
- }
- else { /* not modified - skip */
- do {
- INC_BA(baddr);
- } while (!IS_FA(screen_buf[baddr]));
- }
- } while (baddr != sbaddr);
- } else {
- Boolean any = False;
- int nbytes = 0;
-
- /*
- * If we're in SSCP-LU mode, the starting point is where the
- * host left the cursor.
- */
- if (IN_SSCP)
- baddr = sscp_start;
-
- do {
- if (screen_buf[baddr]) {
- insert_sa(baddr,
- ¤t_fg,
- ¤t_gr,
- ¤t_cs,
- &any);
- if (ea_buf[baddr].cs & CS_GE) {
- space3270out(1);
- *obptr++ = ORDER_GE;
- if (any)
- trace_ds("' ");
- trace_ds(" GraphicEscape ");
- any = False;
- }
- space3270out(1);
- *obptr++ = cg2ebc[screen_buf[baddr]];
- if (!any)
- trace_ds("'");
- trace_ds(see_ebc(cg2ebc[screen_buf[baddr]]));
- any = True;
- nbytes++;
- }
- INC_BA(baddr);
-
- /*
- * If we're in SSCP-LU mode, end the return value at
- * 255 bytes, or where the screen wraps.
- */
- if (IN_SSCP && (nbytes >= 255 || !baddr))
- break;
- } while (baddr != 0);
- if (any)
- trace_ds("'");
- }
-
- rm_done:
- trace_ds("\n");
- net_output();
- }
-
- /*
- * Calculate the proper 3270 DS value for an internal field attribute.
- */
- static unsigned char
- calc_fa(unsigned char fa)
- {
- register unsigned char r = 0x00;
-
- if (FA_IS_PROTECTED(fa))
- r |= 0x20;
- if (FA_IS_NUMERIC(fa))
- r |= 0x10;
- if (FA_IS_MODIFIED(fa))
- r |= 0x01;
- r |= ((fa & FA_INTENSITY) << 2);
- return r;
- }
-
- /*
- * Process a 3270 Read-Buffer command and transmit the data back to the
- * host.
- */
- void
- ctlr_read_buffer(unsigned char aid_byte)
- {
- register int baddr;
- unsigned char fa;
- Boolean any = False;
- int attr_count = 0;
- unsigned char current_fg = 0x00;
- unsigned char current_gr = 0x00;
- unsigned char current_cs = 0x00;
-
- trace_ds("> ");
- obptr = obuf;
-
- space3270out(3);
- *obptr++ = aid_byte;
- ENCODE_BADDR(obptr, cursor_addr);
- trace_ds("%s%s", see_aid(aid_byte), rcba(cursor_addr));
-
- baddr = 0;
- do {
- if (IS_FA(screen_buf[baddr])) {
- if (reply_mode == SF_SRM_FIELD) {
- space3270out(2);
- *obptr++ = ORDER_SF;
- } else {
- space3270out(4);
- *obptr++ = ORDER_SFE;
- attr_count = obptr - obuf;
- *obptr++ = 1; /* for now */
- *obptr++ = XA_3270;
- }
- fa = calc_fa(screen_buf[baddr]);
- *obptr++ = code_table[fa];
- if (any)
- trace_ds("'");
- trace_ds(" StartField%s%s%s",
- (reply_mode == SF_SRM_FIELD) ? "" : "Extended",
- rcba(baddr), see_attr(fa));
- if (reply_mode != SF_SRM_FIELD) {
- if (ea_buf[baddr].fg) {
- space3270out(2);
- *obptr++ = XA_FOREGROUND;
- *obptr++ = ea_buf[baddr].fg;
- trace_ds("%s", see_efa(XA_FOREGROUND,
- ea_buf[baddr].fg));
- (*(obuf + attr_count))++;
- }
- if (ea_buf[baddr].gr) {
- space3270out(2);
- *obptr++ = XA_HIGHLIGHTING;
- *obptr++ = ea_buf[baddr].gr | 0xf0;
- trace_ds("%s", see_efa(XA_HIGHLIGHTING,
- ea_buf[baddr].gr | 0xf0));
- (*(obuf + attr_count))++;
- }
- if (ea_buf[baddr].cs & CS_MASK) {
- space3270out(2);
- *obptr++ = XA_CHARSET;
- *obptr++ =
- (ea_buf[baddr].cs & CS_MASK) | 0xf0;
- trace_ds("%s", see_efa(XA_CHARSET,
- (ea_buf[baddr].cs & CS_MASK) | 0xf0));
- (*(obuf + attr_count))++;
- }
- }
- any = False;
- } else {
- insert_sa(baddr,
- ¤t_fg,
- ¤t_gr,
- ¤t_cs,
- &any);
- if (ea_buf[baddr].cs & CS_GE) {
- space3270out(1);
- *obptr++ = ORDER_GE;
- if (any)
- trace_ds("'");
- trace_ds(" GraphicEscape");
- any = False;
- }
- space3270out(1);
- *obptr++ = cg2ebc[screen_buf[baddr]];
- if (cg2ebc[screen_buf[baddr]] <= 0x3f ||
- cg2ebc[screen_buf[baddr]] == 0xff) {
- if (any)
- trace_ds("'");
-
- trace_ds(" %s", see_ebc(cg2ebc[screen_buf[baddr]]));
- any = False;
- } else {
- if (!any)
- trace_ds(" '");
- trace_ds("%s", see_ebc(cg2ebc[screen_buf[baddr]]));
- any = True;
- }
- }
- INC_BA(baddr);
- } while (baddr != 0);
- if (any)
- trace_ds("'");
-
- trace_ds("\n");
- net_output();
- }
-
- #if defined(X3270_TRACE) /*[*/
- /*
- * Construct a 3270 command to reproduce the current state of the display.
- */
- void
- ctlr_snap_buffer(void)
- {
- register int baddr = 0;
- int attr_count;
- unsigned char current_fg = 0x00;
- unsigned char current_gr = 0x00;
- unsigned char current_cs = 0x00;
- unsigned char av;
-
- space3270out(2);
- *obptr++ = screen_alt ? CMD_EWA : CMD_EW;
- *obptr++ = code_table[0];
-
- do {
- if (IS_FA(screen_buf[baddr])) {
- space3270out(4);
- *obptr++ = ORDER_SFE;
- attr_count = obptr - obuf;
- *obptr++ = 1; /* for now */
- *obptr++ = XA_3270;
- *obptr++ = code_table[calc_fa(screen_buf[baddr])];
- if (ea_buf[baddr].fg) {
- space3270out(2);
- *obptr++ = XA_FOREGROUND;
- *obptr++ = ea_buf[baddr].fg;
- (*(obuf + attr_count))++;
- }
- if (ea_buf[baddr].gr) {
- space3270out(2);
- *obptr++ = XA_HIGHLIGHTING;
- *obptr++ = ea_buf[baddr].gr | 0xf0;
- (*(obuf + attr_count))++;
- }
- if (ea_buf[baddr].cs & CS_MASK) {
- space3270out(2);
- *obptr++ = XA_CHARSET;
- *obptr++ = (ea_buf[baddr].cs & CS_MASK) | 0xf0;
- (*(obuf + attr_count))++;
- }
- } else {
- av = ea_buf[baddr].fg;
- if (current_fg != av) {
- current_fg = av;
- space3270out(3);
- *obptr++ = ORDER_SA;
- *obptr++ = XA_FOREGROUND;
- *obptr++ = av;
- }
- av = ea_buf[baddr].gr;
- if (av)
- av |= 0xf0;
- if (current_gr != av) {
- current_gr = av;
- space3270out(3);
- *obptr++ = ORDER_SA;
- *obptr++ = XA_HIGHLIGHTING;
- *obptr++ = av;
- }
- av = ea_buf[baddr].cs & CS_MASK;
- if (av)
- av |= 0xf0;
- if (current_cs != av) {
- current_cs = av;
- space3270out(3);
- *obptr++ = ORDER_SA;
- *obptr++ = XA_CHARSET;
- *obptr++ = av;
- }
- if (ea_buf[baddr].cs & CS_GE) {
- space3270out(1);
- *obptr++ = ORDER_GE;
- }
- space3270out(1);
- *obptr++ = cg2ebc[screen_buf[baddr]];
- }
- INC_BA(baddr);
- } while (baddr != 0);
-
- space3270out(4);
- *obptr++ = ORDER_SBA;
- ENCODE_BADDR(obptr, cursor_addr);
- *obptr++ = ORDER_IC;
- }
-
- /*
- * Construct a 3270 command to reproduce the reply mode.
- * Returns a Boolean indicating if one is necessary.
- */
- Boolean
- ctlr_snap_modes(void)
- {
- int i;
-
- if (!IN_3270 || reply_mode == SF_SRM_FIELD)
- return False;
-
- space3270out(6 + crm_nattr);
- *obptr++ = CMD_WSF;
- *obptr++ = 0x00; /* implicit length */
- *obptr++ = 0x00;
- *obptr++ = SF_SET_REPLY_MODE;
- *obptr++ = 0x00; /* partition 0 */
- *obptr++ = reply_mode;
- if (reply_mode == SF_SRM_CHAR)
- for (i = 0; i < crm_nattr; i++)
- *obptr++ = crm_attr[i];
- return True;
- }
- #endif /*]*/
-
-
- /*
- * Process a 3270 Erase All Unprotected command.
- */
- void
- ctlr_erase_all_unprotected(void)
- {
- register int baddr, sbaddr;
- unsigned char fa;
- Boolean f;
-
- kybd_inhibit(False);
-
- ALL_CHANGED;
- if (formatted) {
- /* find first field attribute */
- baddr = 0;
- do {
- if (IS_FA(screen_buf[baddr]))
- break;
- INC_BA(baddr);
- } while (baddr != 0);
- sbaddr = baddr;
- f = False;
- do {
- fa = screen_buf[baddr];
- if (!FA_IS_PROTECTED(fa)) {
- mdt_clear(&screen_buf[baddr]);
- do {
- INC_BA(baddr);
- if (!f) {
- cursor_move(baddr);
- f = True;
- }
- if (!IS_FA(screen_buf[baddr])) {
- ctlr_add(baddr, CG_null, 0);
- }
- } while (!IS_FA(screen_buf[baddr]));
- }
- else {
- do {
- INC_BA(baddr);
- } while (!IS_FA(screen_buf[baddr]));
- }
- } while (baddr != sbaddr);
- if (!f)
- cursor_move(0);
- } else {
- ctlr_clear(True);
- }
- aid = AID_NO;
- do_reset(False);
- }
-
-
-
- /*
- * Process a 3270 Write command.
- */
- void
- ctlr_write(unsigned char buf[], int buflen, Boolean erase)
- {
- register unsigned char *cp;
- register int baddr;
- unsigned char *current_fa;
- unsigned char new_attr;
- Boolean last_cmd;
- Boolean last_zpt;
- Boolean wcc_keyboard_restore, wcc_sound_alarm;
- Boolean ra_ge;
- int i;
- unsigned char na;
- int any_fa;
- unsigned char efa_fg;
- unsigned char efa_gr;
- unsigned char efa_cs;
- const char *paren = "(";
- enum { NONE, ORDER, SBA, TEXT, NULLCH } previous = NONE;
-
- #define END_TEXT0 { if (previous == TEXT) trace_ds("'"); }
- #define END_TEXT(cmd) { END_TEXT0; trace_ds(" %s", cmd); }
-
- #define ATTR2FA(attr) \
- (FA_BASE | \
- (((attr) & 0x20) ? FA_PROTECT : 0) | \
- (((attr) & 0x10) ? FA_NUMERIC : 0) | \
- (((attr) & 0x01) ? FA_MODIFY : 0) | \
- (((attr) >> 2) & FA_INTENSITY))
- #define START_FIELDx(fa) { \
- current_fa = &(screen_buf[buffer_addr]); \
- ctlr_add(buffer_addr, fa, 0); \
- ctlr_add_fg(buffer_addr, 0); \
- ctlr_add_gr(buffer_addr, 0); \
- trace_ds(see_attr(fa)); \
- formatted = True; \
- }
- #define START_FIELD0 { START_FIELDx(FA_BASE); }
- #define START_FIELD(attr) { \
- new_attr = ATTR2FA(attr); \
- START_FIELDx(new_attr); \
- }
-
- kybd_inhibit(False);
-
- if (buflen < 2)
- return;
-
- default_fg = 0;
- default_gr = 0;
- default_cs = 0;
- trace_primed = True;
- buffer_addr = cursor_addr;
- if (WCC_RESET(buf[1])) {
- if (erase)
- reply_mode = SF_SRM_FIELD;
- trace_ds("%sreset", paren);
- paren = ",";
- }
- wcc_sound_alarm = WCC_SOUND_ALARM(buf[1]);
- if (wcc_sound_alarm) {
- trace_ds("%salarm", paren);
- paren = ",";
- }
- wcc_keyboard_restore = WCC_KEYBOARD_RESTORE(buf[1]);
- if (wcc_keyboard_restore)
- ticking_stop();
- if (wcc_keyboard_restore) {
- trace_ds("%srestore", paren);
- paren = ",";
- }
-
- if (WCC_RESET_MDT(buf[1])) {
- trace_ds("%sresetMDT", paren);
- paren = ",";
- baddr = 0;
- if (appres.modified_sel)
- ALL_CHANGED;
- do {
- if (IS_FA(screen_buf[baddr])) {
- mdt_clear(&screen_buf[baddr]);
- }
- INC_BA(baddr);
- } while (baddr != 0);
- }
- if (strcmp(paren, "("))
- trace_ds(")");
-
- last_cmd = True;
- last_zpt = False;
- current_fa = get_field_attribute(buffer_addr);
- for (cp = &buf[2]; cp < (buf + buflen); cp++) {
- switch (*cp) {
- case ORDER_SF: /* start field */
- END_TEXT("StartField");
- if (previous != SBA)
- trace_ds(rcba(buffer_addr));
- previous = ORDER;
- cp++; /* skip field attribute */
- START_FIELD(*cp);
- ctlr_add_fg(buffer_addr, 0);
- INC_BA(buffer_addr);
- last_cmd = True;
- last_zpt = False;
- break;
- case ORDER_SBA: /* set buffer address */
- cp += 2; /* skip buffer address */
- buffer_addr = DECODE_BADDR(*(cp-1), *cp);
- END_TEXT("SetBufferAddress");
- previous = SBA;
- trace_ds(rcba(buffer_addr));
- if (buffer_addr >= COLS * ROWS) {
- trace_ds(" [invalid address, write command terminated]\n");
- /* Let a script go. */
- sms_host_output();
- return;
- }
- current_fa = get_field_attribute(buffer_addr);
- last_cmd = True;
- last_zpt = False;
- break;
- case ORDER_IC: /* insert cursor */
- END_TEXT("InsertCursor");
- if (previous != SBA)
- trace_ds(rcba(buffer_addr));
- previous = ORDER;
- cursor_move(buffer_addr);
- last_cmd = True;
- last_zpt = False;
- break;
- case ORDER_PT: /* program tab */
- END_TEXT("ProgramTab");
- previous = ORDER;
- /*
- * If the buffer address is the field attribute of
- * of an unprotected field, simply advance one
- * position.
- */
- if (IS_FA(screen_buf[buffer_addr]) &&
- !FA_IS_PROTECTED(screen_buf[buffer_addr])) {
- INC_BA(buffer_addr);
- last_zpt = False;
- last_cmd = True;
- break;
- }
- /*
- * Otherwise, advance to the first position of the
- * next unprotected field.
- */
- baddr = next_unprotected(buffer_addr);
- if (baddr < buffer_addr)
- baddr = 0;
- /*
- * Null out the remainder of the current field -- even
- * if protected -- if the PT doesn't follow a command
- * or order, or (honestly) if the last order we saw was
- * a null-filling PT that left the buffer address at 0.
- */
- if (!last_cmd || last_zpt) {
- trace_ds("(nulling)");
- while ((buffer_addr != baddr) &&
- (!IS_FA(screen_buf[buffer_addr]))) {
- ctlr_add(buffer_addr, CG_null, 0);
- INC_BA(buffer_addr);
- }
- if (baddr == 0)
- last_zpt = True;
- } else
- last_zpt = False;
- buffer_addr = baddr;
- last_cmd = True;
- break;
- case ORDER_RA: /* repeat to address */
- END_TEXT("RepeatToAddress");
- cp += 2; /* skip buffer address */
- baddr = DECODE_BADDR(*(cp-1), *cp);
- trace_ds(rcba(baddr));
- cp++; /* skip char to repeat */
- if (*cp == ORDER_GE){
- ra_ge = True;
- trace_ds("GraphicEscape");
- cp++;
- } else
- ra_ge = False;
- previous = ORDER;
- if (*cp)
- trace_ds("'");
- trace_ds("%s", see_ebc(*cp));
- if (*cp)
- trace_ds("'");
- if (baddr >= COLS * ROWS) {
- trace_ds(" [invalid address, write command terminated]\n");
- /* Let a script go. */
- sms_host_output();
- return;
- }
- do {
- if (ra_ge)
- ctlr_add(buffer_addr, ebc2cg0[*cp],
- CS_GE);
- else if (default_cs)
- ctlr_add(buffer_addr, ebc2cg0[*cp], 1);
- else
- ctlr_add(buffer_addr, ebc2cg[*cp], 0);
- ctlr_add_fg(buffer_addr, default_fg);
- ctlr_add_gr(buffer_addr, default_gr);
- INC_BA(buffer_addr);
- } while (buffer_addr != baddr);
- current_fa = get_field_attribute(buffer_addr);
- last_cmd = True;
- last_zpt = False;
- break;
- case ORDER_EUA: /* erase unprotected to address */
- cp += 2; /* skip buffer address */
- baddr = DECODE_BADDR(*(cp-1), *cp);
- END_TEXT("EraseUnprotectedAll");
- if (previous != SBA)
- trace_ds(rcba(baddr));
- previous = ORDER;
- if (baddr >= COLS * ROWS) {
- trace_ds(" [invalid address, write command terminated]\n");
- /* Let a script go. */
- sms_host_output();
- return;
- }
- do {
- if (IS_FA(screen_buf[buffer_addr]))
- current_fa = &(screen_buf[buffer_addr]);
- else if (!FA_IS_PROTECTED(*current_fa)) {
- ctlr_add(buffer_addr, CG_null, 0);
- }
- INC_BA(buffer_addr);
- } while (buffer_addr != baddr);
- current_fa = get_field_attribute(buffer_addr);
- last_cmd = True;
- last_zpt = False;
- break;
- case ORDER_GE: /* graphic escape */
- END_TEXT("GraphicEscape ");
- cp++; /* skip char */
- previous = ORDER;
- if (*cp)
- trace_ds("'");
- trace_ds("%s", see_ebc(*cp));
- if (*cp)
- trace_ds("'");
- ctlr_add(buffer_addr, ebc2cg0[*cp], CS_GE);
- ctlr_add_fg(buffer_addr, default_fg);
- ctlr_add_gr(buffer_addr, default_gr);
- INC_BA(buffer_addr);
- current_fa = get_field_attribute(buffer_addr);
- last_cmd = False;
- last_zpt = False;
- break;
- case ORDER_MF: /* modify field */
- END_TEXT("ModifyField");
- if (previous != SBA)
- trace_ds(rcba(buffer_addr));
- previous = ORDER;
- cp++;
- na = *cp;
- if (IS_FA(screen_buf[buffer_addr])) {
- if (na == 0) {
- INC_BA(buffer_addr);
- } else {
- for (i = 0; i < (int)na; i++) {
- cp++;
- if (*cp == XA_3270) {
- trace_ds(" 3270");
- cp++;
- new_attr = ATTR2FA(*cp);
- ctlr_add(buffer_addr,
- new_attr,
- 0);
- trace_ds(see_attr(new_attr));
- } else if (*cp == XA_FOREGROUND) {
- trace_ds("%s",
- see_efa(*cp,
- *(cp + 1)));
- cp++;
- if (appres.m3279)
- ctlr_add_fg(buffer_addr, *cp);
- } else if (*cp == XA_HIGHLIGHTING) {
- trace_ds("%s",
- see_efa(*cp,
- *(cp + 1)));
- cp++;
- ctlr_add_gr(buffer_addr, *cp & 0x07);
- } else if (*cp == XA_CHARSET) {
- int cs = 0;
-
- trace_ds("%s",
- see_efa(*cp,
- *(cp + 1)));
- cp++;
- if (*cp == 0xf1)
- cs = 1;
- ctlr_add(buffer_addr,
- screen_buf[buffer_addr], cs);
- } else if (*cp == XA_ALL) {
- trace_ds("%s",
- see_efa(*cp,
- *(cp + 1)));
- cp++;
- } else {
- trace_ds("%s[unsupported]", see_efa(*cp, *(cp + 1)));
- cp++;
- }
- }
- }
- INC_BA(buffer_addr);
- } else
- cp += na * 2;
- last_cmd = True;
- last_zpt = False;
- break;
- case ORDER_SFE: /* start field extended */
- END_TEXT("StartFieldExtended");
- if (previous != SBA)
- trace_ds(rcba(buffer_addr));
- previous = ORDER;
- cp++; /* skip order */
- na = *cp;
- any_fa = 0;
- efa_fg = 0;
- efa_gr = 0;
- efa_cs = 0;
- for (i = 0; i < (int)na; i++) {
- cp++;
- if (*cp == XA_3270) {
- trace_ds(" 3270");
- cp++;
- START_FIELD(*cp);
- any_fa++;
- } else if (*cp == XA_FOREGROUND) {
- trace_ds("%s", see_efa(*cp, *(cp + 1)));
- cp++;
- if (appres.m3279)
- efa_fg = *cp;
- } else if (*cp == XA_HIGHLIGHTING) {
- trace_ds("%s", see_efa(*cp, *(cp + 1)));
- cp++;
- efa_gr = *cp & 0x07;
- } else if (*cp == XA_CHARSET) {
- trace_ds("%s", see_efa(*cp, *(cp + 1)));
- cp++;
- if (*cp == 0xf1)
- efa_cs = 1;
- } else if (*cp == XA_ALL) {
- trace_ds("%s", see_efa(*cp, *(cp + 1)));
- cp++;
- } else {
- trace_ds("%s[unsupported]", see_efa(*cp, *(cp + 1)));
- cp++;
- }
- }
- if (!any_fa)
- START_FIELD0;
- ctlr_add(buffer_addr, screen_buf[buffer_addr], efa_cs);
- ctlr_add_fg(buffer_addr, efa_fg);
- ctlr_add_gr(buffer_addr, efa_gr);
- INC_BA(buffer_addr);
- last_cmd = True;
- last_zpt = False;
- break;
- case ORDER_SA: /* set attribute */
- END_TEXT("SetAttribtue");
- previous = ORDER;
- cp++;
- if (*cp == XA_FOREGROUND) {
- trace_ds("%s", see_efa(*cp, *(cp + 1)));
- if (appres.m3279)
- default_fg = *(cp + 1);
- } else if (*cp == XA_HIGHLIGHTING) {
- trace_ds("%s", see_efa(*cp, *(cp + 1)));
- default_gr = *(cp + 1) & 0x07;
- } else if (*cp == XA_ALL) {
- trace_ds("%s", see_efa(*cp, *(cp + 1)));
- default_fg = 0;
- default_gr = 0;
- default_cs = 0;
- } else if (*cp == XA_CHARSET) {
- trace_ds("%s", see_efa(*cp, *(cp + 1)));
- default_cs = (*(cp + 1) == 0xf1) ? 1 : 0;
- } else
- trace_ds("%s[unsupported]",
- see_efa(*cp, *(cp + 1)));
- cp++;
- last_cmd = True;
- last_zpt = False;
- break;
- case FCORDER_SUB: /* format control orders */
- case FCORDER_DUP:
- case FCORDER_FM:
- case FCORDER_FF:
- case FCORDER_CR:
- case FCORDER_NL:
- case FCORDER_EM:
- case FCORDER_EO:
- END_TEXT(see_ebc(*cp));
- previous = ORDER;
- ctlr_add(buffer_addr, ebc2cg[*cp], default_cs);
- ctlr_add_fg(buffer_addr, default_fg);
- ctlr_add_gr(buffer_addr, default_gr);
- INC_BA(buffer_addr);
- last_cmd = True;
- last_zpt = False;
- break;
- case FCORDER_NULL:
- END_TEXT("NULL");
- previous = NULLCH;
- ctlr_add(buffer_addr, ebc2cg[*cp], default_cs);
- ctlr_add_fg(buffer_addr, default_fg);
- ctlr_add_gr(buffer_addr, default_gr);
- INC_BA(buffer_addr);
- last_cmd = False;
- last_zpt = False;
- break;
- default: /* enter character */
- if (*cp <= 0x3F) {
- END_TEXT("ILLEGAL_ORDER");
- trace_ds("%s", see_ebc(*cp));
- last_cmd = True;
- last_zpt = False;
- break;
- }
- if (previous != TEXT)
- trace_ds(" '");
- previous = TEXT;
- trace_ds("%s", see_ebc(*cp));
- ctlr_add(buffer_addr, ebc2cg[*cp], default_cs);
- ctlr_add_fg(buffer_addr, default_fg);
- ctlr_add_gr(buffer_addr, default_gr);
- INC_BA(buffer_addr);
- last_cmd = False;
- last_zpt = False;
- break;
- }
- }
- set_formatted();
- END_TEXT0;
- trace_ds("\n");
- if (wcc_keyboard_restore) {
- aid = AID_NO;
- do_reset(False);
- } else if (kybdlock & KL_OIA_TWAIT) {
- kybdlock_clr(KL_OIA_TWAIT, "ctlr_write");
- status_syswait();
- }
- if (wcc_sound_alarm)
- ring_bell();
-
- trace_primed = False;
-
- ps_process();
-
- /* Let a script go. */
- sms_host_output();
- }
-
- #undef START_FIELDx
- #undef START_FIELD0
- #undef START_FIELD
- #undef END_TEXT0
- #undef END_TEXT
-
- /*
- * Write SSCP-LU data, which is quite a bit dumber than regular 3270
- * output.
- */
- void
- ctlr_write_sscp_lu(unsigned char buf[], int buflen)
- {
- int i;
- unsigned char *cp = buf;
- int s_row;
- unsigned char c;
- int baddr;
- unsigned char fa;
-
- /*
- * The 3174 Functionl Description says that anything but NL, NULL, FM,
- * or DUP is to be displayed as a graphic. However, to deal with
- * badly-behaved hosts, we filter out SF, IC and SBA sequences, and
- * we display other control codes as spaces.
- */
-
- trace_ds("SSCP-LU data\n");
- for (i = 0; i < buflen; cp++, i++) {
- switch (*cp) {
- case FCORDER_NL:
- /*
- * Insert NULLs to the end of the line and advance to
- * the beginning of the next line.
- */
- s_row = buffer_addr / COLS;
- while ((buffer_addr / COLS) == s_row) {
- ctlr_add(buffer_addr, ebc2cg[0], default_cs);
- ctlr_add_fg(buffer_addr, default_fg);
- ctlr_add_gr(buffer_addr, default_gr);
- INC_BA(buffer_addr);
- }
- break;
-
- case ORDER_SF: /* some hosts forget their talking SSCP-LU */
- cp++;
- i++;
- fa = ATTR2FA(*cp);
- trace_ds(" StartField%s %s [translated to space]\n",
- rcba(buffer_addr), see_attr(fa));
- ctlr_add(buffer_addr, CG_space, default_cs);
- ctlr_add_fg(buffer_addr, default_fg);
- ctlr_add_gr(buffer_addr, default_gr);
- INC_BA(buffer_addr);
- break;
- case ORDER_IC:
- trace_ds(" InsertCursor%s [ignored]\n",
- rcba(buffer_addr));
- break;
- case ORDER_SBA:
- baddr = DECODE_BADDR(*(cp+1), *(cp+2));
- trace_ds(" SetBufferAddress%s [ignored]\n", rcba(baddr));
- cp += 2;
- i += 2;
- break;
-
- case ORDER_GE:
- cp++;
- if (++i >= buflen)
- break;
- if (*cp <= 0x40)
- c = CG_space;
- else
- c = ebc2cg0[*cp];
- ctlr_add(buffer_addr, c, CS_GE);
- ctlr_add_fg(buffer_addr, default_fg);
- ctlr_add_gr(buffer_addr, default_gr);
- INC_BA(buffer_addr);
- break;
-
- default:
- if (*cp == FCORDER_NULL)
- c = CG_space;
- else if (*cp == FCORDER_FM)
- c = CG_asterisk;
- else if (*cp == FCORDER_DUP)
- c = CG_semicolon;
- else if (*cp < 0x40) {
- trace_ds(" X'%02x') [translated to space]\n",
- *cp);
- c = CG_space; /* technically not necessary */
- } else
- c = ebc2cg[*cp];
- ctlr_add(buffer_addr, c, default_cs);
- ctlr_add_fg(buffer_addr, default_fg);
- ctlr_add_gr(buffer_addr, default_gr);
- INC_BA(buffer_addr);
- break;
- }
- }
- cursor_move(buffer_addr);
- sscp_start = buffer_addr;
-
- /* Unlock the keyboard. */
- aid = AID_NO;
- do_reset(False);
-
- /* Let a script go. */
- sms_host_output();
- }
-
- /*
- * Process pending input.
- */
- void
- ps_process(void)
- {
- while (run_ta())
- ;
- sms_continue();
-
- /* Process file transfers. */
- if (ft_state != FT_NONE && /* transfer in progress */
- formatted && /* screen is formatted */
- !screen_alt && /* 24x80 screen */
- !kybdlock && /* keyboard not locked */
- /* magic field */
- IS_FA(screen_buf[1919]) && FA_IS_SKIP(screen_buf[1919])) {
- ft_cut_data();
- }
- }
-
- /*
- * Tell me if there is any data on the screen.
- */
- Boolean
- ctlr_any_data(void)
- {
- register unsigned char *c = screen_buf;
- register int i;
- register unsigned char oc;
-
- for (i = 0; i < ROWS*COLS; i++) {
- oc = *c++;
- if (!IS_FA(oc) && !IsBlank(oc))
- return True;
- }
- return False;
- }
-
- /*
- * Clear the text (non-status) portion of the display. Also resets the cursor
- * and buffer addresses and extended attributes.
- */
- void
- ctlr_clear(Boolean can_snap)
- {
- /* Snap any data that is about to be lost into the trace file. */
- if (ctlr_any_data()) {
- #if defined(X3270_TRACE) /*[*/
- if (can_snap && !trace_skipping && toggled(SCREEN_TRACE))
- trace_screen();
- #endif /*]*/
- scroll_save(maxROWS, ever_3270 ? False : True);
- }
- #if defined(X3270_TRACE) /*[*/
- trace_skipping = False;
- #endif /*]*/
-
- /* Clear the screen. */
- (void) memset((char *)screen_buf, 0, ROWS*COLS);
- (void) memset((char *)ea_buf, 0, ROWS*COLS*sizeof(struct ea));
- ALL_CHANGED;
- cursor_move(0);
- buffer_addr = 0;
- unselect(0, ROWS*COLS);
- formatted = False;
- default_fg = 0;
- default_gr = 0;
- sscp_start = 0;
- }
-
- /*
- * Fill the screen buffer with blanks.
- */
- static void
- ctlr_blanks(void)
- {
- (void) memset((char *)screen_buf, CG_space, ROWS*COLS);
- ALL_CHANGED;
- cursor_move(0);
- buffer_addr = 0;
- unselect(0, ROWS*COLS);
- formatted = False;
- }
-
-
- /*
- * Change a character in the 3270 buffer.
- */
- void
- ctlr_add(int baddr, unsigned char c, unsigned char cs)
- {
- unsigned char oc;
-
- if ((oc = screen_buf[baddr]) != c || ea_buf[baddr].cs != cs) {
- if (trace_primed && !IsBlank(oc)) {
- #if defined(X3270_TRACE) /*[*/
- if (toggled(SCREEN_TRACE))
- trace_screen();
- #endif /*]*/
- scroll_save(maxROWS, False);
- trace_primed = False;
- }
- if (SELECTED(baddr))
- unselect(baddr, 1);
- ONE_CHANGED(baddr);
- screen_buf[baddr] = c;
- ea_buf[baddr].cs = cs;
- }
- }
-
- /*
- * Change the graphic rendition of a character in the 3270 buffer.
- */
- void
- ctlr_add_gr(int baddr, unsigned char gr)
- {
- if (ea_buf[baddr].gr != gr) {
- if (SELECTED(baddr))
- unselect(baddr, 1);
- ONE_CHANGED(baddr);
- ea_buf[baddr].gr = gr;
- if (gr & GR_BLINK)
- blink_start();
- }
- }
-
- /*
- * Change the foreground color for a character in the 3270 buffer.
- */
- void
- ctlr_add_fg(int baddr, unsigned char color)
- {
- if (!appres.m3279)
- return;
- if ((color & 0xf0) != 0xf0)
- color = 0;
- if (ea_buf[baddr].fg != color) {
- if (SELECTED(baddr))
- unselect(baddr, 1);
- ONE_CHANGED(baddr);
- ea_buf[baddr].fg = color;
- }
- }
-
- #if defined(X3270_ANSI) /*[*/
- /*
- * Change the background color for a character in the 3270 buffer.
- */
- void
- ctlr_add_bg(int baddr, unsigned char color)
- {
- if (!appres.m3279)
- return;
- if ((color & 0xf0) != 0xf0)
- color = 0;
- if (ea_buf[baddr].bg != color) {
- if (SELECTED(baddr))
- unselect(baddr, 1);
- ONE_CHANGED(baddr);
- ea_buf[baddr].bg = color;
- }
- }
- #endif /*]*/
-
- /*
- * Copy a block of characters in the 3270 buffer, optionally including all of
- * the extended attributes. (The character set, which is actually kept in the
- * extended attributes, is considered part of the characters here.)
- */
- void
- ctlr_bcopy(int baddr_from, int baddr_to, int count, int move_ea)
- {
- /* Move the characters. */
- if (memcmp((char *) &screen_buf[baddr_from],
- (char *) &screen_buf[baddr_to],
- count)) {
- (void) memmove(&screen_buf[baddr_to], &screen_buf[baddr_from],
- count);
- REGION_CHANGED(baddr_to, baddr_to + count);
- /*
- * For the time being, if any selected text shifts around on
- * the screen, unhighlight it. Eventually there should be
- * logic for preserving the highlight if the *all* of the
- * selected text moves.
- */
- if (area_is_selected(baddr_to, count))
- unselect(baddr_to, count);
- }
-
- /*
- * If we aren't supposed to move all the extended attributes, move
- * the character sets separately.
- */
- if (!move_ea) {
- int i;
- int any = 0;
- int start, end, inc;
-
- if (baddr_to < baddr_from || baddr_from + count < baddr_to) {
- /* Scan forward. */
- start = 0;
- end = count + 1;
- inc = 1;
- } else {
- /* Scan backward. */
- start = count - 1;
- end = -1;
- inc = -1;
- }
-
- for (i = start; i != end; i += inc) {
- if (ea_buf[baddr_to+i].cs != ea_buf[baddr_from+i].cs) {
- ea_buf[baddr_to+i].cs = ea_buf[baddr_from+i].cs;
- REGION_CHANGED(baddr_to + i, baddr_to + i + 1);
- any++;
- }
- }
- if (any && area_is_selected(baddr_to, count))
- unselect(baddr_to, count);
- }
-
- /* Move extended attributes. */
- if (move_ea && memcmp((char *) &ea_buf[baddr_from],
- (char *) &ea_buf[baddr_to],
- count*sizeof(struct ea))) {
- (void) memmove(&ea_buf[baddr_to], &ea_buf[baddr_from],
- count*sizeof(struct ea));
- REGION_CHANGED(baddr_to, baddr_to + count);
- }
- }
-
- #if defined(X3270_ANSI) /*[*/
- /*
- * Erase a region of the 3270 buffer, optionally clearing extended attributes
- * as well.
- */
- void
- ctlr_aclear(int baddr, int count, int clear_ea)
- {
- if (memcmp((char *) &screen_buf[baddr], (char *) zero_buf, count)) {
- (void) memset((char *) &screen_buf[baddr], 0, count);
- REGION_CHANGED(baddr, baddr + count);
- if (area_is_selected(baddr, count))
- unselect(baddr, count);
- }
- if (clear_ea && memcmp((char *) &ea_buf[baddr], (char *) zero_buf, count*sizeof(struct ea))) {
- (void) memset((char *) &ea_buf[baddr], 0, count*sizeof(struct ea));
- REGION_CHANGED(baddr, baddr + count);
- }
- }
-
- /*
- * Scroll the screen 1 row.
- *
- * This could be accomplished with ctlr_bcopy() and ctlr_aclear(), but this
- * operation is common enough to warrant a separate path.
- */
- void
- ctlr_scroll(void)
- {
- int qty = (ROWS - 1) * COLS;
- Boolean obscured;
-
- /* Make sure nothing is selected. (later this can be fixed) */
- unselect(0, ROWS*COLS);
-
- /* Synchronize pending changes prior to this. */
- obscured = screen_obscured();
- if (!obscured && screen_changed)
- screen_disp();
-
- /* Move screen_buf and ea_buf. */
- (void) memmove(&screen_buf[0], &screen_buf[COLS], qty);
- (void) memmove(&ea_buf[0], &ea_buf[COLS],
- qty * sizeof(struct ea));
-
- /* Clear the last line. */
- (void) memset((char *) &screen_buf[qty], 0, COLS);
- (void) memset((char *) &ea_buf[qty], 0, COLS * sizeof(struct ea));
-
- /* Update the screen. */
- if (obscured) {
- ALL_CHANGED;
- } else {
- screen_scroll();
- }
- }
- #endif /*]*/
-
- /*
- * Note that a particular region of the screen has changed.
- */
- void
- ctlr_changed(int bstart, int bend)
- {
- REGION_CHANGED(bstart, bend);
- }
-
- #if defined(X3270_ANSI) /*[*/
- /*
- * Swap the regular and alternate screen buffers
- */
- void
- ctlr_altbuffer(Boolean alt)
- {
- unsigned char *stmp;
- struct ea *etmp;
-
- if (alt != is_altbuffer) {
-
- stmp = screen_buf;
- screen_buf = ascreen_buf;
- ascreen_buf = stmp;
-
- etmp = ea_buf;
- ea_buf = aea_buf;
- aea_buf = etmp;
-
- is_altbuffer = alt;
- ALL_CHANGED;
- unselect(0, ROWS*COLS);
-
- /*
- * There may be blinkers on the alternate screen; schedule one
- * iteration just in case.
- */
- blink_start();
- }
- }
- #endif /*]*/
-
-
- /*
- * Set or clear the MDT on an attribute
- */
- void
- mdt_set(unsigned char *fa)
- {
- if (*fa & FA_MODIFY)
- return;
- *fa |= FA_MODIFY;
- if (appres.modified_sel)
- ALL_CHANGED;
- }
-
- void
- mdt_clear(unsigned char *fa)
- {
- if (!(*fa & FA_MODIFY))
- return;
- *fa &= ~FA_MODIFY;
- if (appres.modified_sel)
- ALL_CHANGED;
- }
-
-
- /*
- * Support for screen-size swapping for scrolling
- */
- void
- ctlr_shrink(void)
- {
- (void) memset((char *)screen_buf,
- *debugging_font ? CG_space : CG_null,
- ROWS*COLS);
- ALL_CHANGED;
- screen_disp();
- }
-
-
- /*
- * Transaction timing. The time between sending an interrupt (PF, PA, Enter,
- * Clear) and the host unlocking the keyboard is indicated on the status line
- * to an accuracy of 0.1 seconds. If we don't repaint the screen before we see
- * the unlock, the time should be fairly accurate.
- */
- static struct timeval t_start;
- static Boolean ticking = False;
- static unsigned long tick_id;
- static struct timeval t_want;
-
- /* Return the difference in milliseconds between two timevals. */
- static long
- delta_msec(struct timeval *t1, struct timeval *t0)
- {
- return (t1->tv_sec - t0->tv_sec) * 1000 +
- (t1->tv_usec - t0->tv_usec + 500) / 1000;
- }
-
- static void
- keep_ticking(void)
- {
- struct timeval t1;
- long msec;
-
- do {
- (void) gettimeofday(&t1, (struct timezone *) 0);
- t_want.tv_sec++;
- msec = delta_msec(&t_want, &t1);
- } while (msec <= 0);
- tick_id = AddTimeOut(msec, keep_ticking);
- status_timing(&t_start, &t1);
- }
-
- void
- ticking_start(Boolean anyway)
- {
- if (!toggled(SHOW_TIMING) && !anyway)
- return;
- status_untiming();
- if (ticking)
- RemoveTimeOut(tick_id);
- ticking = True;
- (void) gettimeofday(&t_start, (struct timezone *) 0);
- tick_id = AddTimeOut(1000, keep_ticking);
- t_want = t_start;
- }
-
- static void
- ticking_stop(void)
- {
- struct timeval t1;
-
- if (!ticking)
- return;
- RemoveTimeOut(tick_id);
- (void) gettimeofday(&t1, (struct timezone *) 0);
- ticking = False;
- status_timing(&t_start, &t1);
- }
-
- void
- toggle_showTiming(struct toggle *t unused, enum toggle_type tt unused)
- {
- if (!toggled(SHOW_TIMING))
- status_untiming();
- }
-
-
- /*
- * No-op toggle.
- */
- void
- toggle_nop(struct toggle *t unused, enum toggle_type tt unused)
- {
- }
-